import World from "./World";
import rand from "./rand";

const pool = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()_+<>?:"{}|,./;\'[]\\`~'

export default class Digi {
  readonly world: World;
  x: number = 0;
  y: number = 0;
  speed: number = 0.05;
  word: string = '';
  d_x: number;
  d_y: number;
  dis: number;
  private dead_zone: number = 0;
  hue: number = 0;
  constructor(world: World) {
    this.world = world;
    this.word = pool[Math.floor(rand(0, pool.length)) % pool.length];

    Math.random() < 0.5 ? '1' : '0';
    const { width, height } = this.world.canvas;
    this.d_x = width / 2;
    this.d_y = height / 2;
    this.dis = this.get_distance();
  }
  calc_dead_zone(dt: number): number {
    return this.dead_zone = dt * (this.speed + this.world.gravity);
  }
  set_destination(x: number, y: number): void {
    this.d_x = x;
    this.d_y = y;
  }
  update(dt: number) {
    const angle = Math.atan2(
      this.y - this.d_y,
      this.x - this.d_x
    );
    this.x += this.speed * dt * Math.cos(angle + Math.PI / 2);
    this.y += this.speed * dt * Math.sin(angle + Math.PI / 2);
    this.x -= this.world.gravity * dt * Math.cos(angle);
    this.y -= this.world.gravity * dt * Math.sin(angle);
    this.dis = this.get_distance();
    if (this.dis <= this.calc_dead_zone(dt))
      this.world.digis.delete(this);
  }
  get_distance() {
    return Math.sqrt(
      Math.pow(this.y - this.d_y, 2) + Math.pow(this.x - this.d_x, 2)
    );
  }
  draw(ctx: CanvasRenderingContext2D) {
    const diff = this.dis - this.dead_zone;
    let alpha = 0;
    const r = this.world.radius;
    if (diff < r / 2) alpha = 0.5 * diff / (r / 2);
    else if (diff < r) alpha = 0.5 * (r - diff) / (r / 2);

    const { actualBoundingBoxAscent, actualBoundingBoxDescent, width } = ctx.measureText(this.word);
    const height = actualBoundingBoxAscent + actualBoundingBoxDescent;

    const scale = 1 + alpha * 2;
    ctx.fillStyle = `hsla(${this.hue}, 100%, 50%, ${alpha})`;
    ctx.save();
    ctx.translate(this.x, this.y);
    ctx.scale(scale, scale);
    ctx.fillText(this.word, -width / 2, -height / 2);
    ctx.restore();
  }
}
